<template>
  <div class="address-selector">
    <!-- 级联选择器模式 -->
    <el-cascader
      v-if="mode === 'cascader'"
      ref="cascader"
      v-model="selectedValues"
      :options="cascaderOptions"
      :props="cascaderProps"
      :placeholder="placeholder"
      :disabled="disabled"
      :clearable="clearable"
      :multiple="multiple"
      :collapse-tags="collapseTags"
      :show-all-levels="showAllLevels"
      :separator="separator"
      :size="size"
      :style="styleWidth"
      :filterable="filterable"
      @change="handleCascaderChange"
      @expand-change="handleExpandChange"
      @blur="handleBlur"
      @focus="handleFocus"
    >
      <template slot-scope="{ node, data }">
        <span>{{ node.label }}</span>
        <span v-if="showCode && data.code" class="code-text">({{ data.code }})</span>
      </template>
    </el-cascader>

    <!-- 下拉选择器模式 -->
    <div v-else-if="mode === 'select'" class="select-mode">
      <el-row :gutter="10">
        <!-- 省份选择 -->
        <el-col :span="levelSpan">
          <el-select
            v-model="selectedProvince"
            :placeholder="provincePlaceholder"
            :disabled="disabled"
            :clearable="clearable"
            :size="size"
            :filterable="filterable"
            @change="handleProvinceChange"
          >
            <el-option
              v-for="province in provinces"
              :key="province.value"
              :label="province.label"
              :value="province.value"
            >
              <span>{{ province.label }}</span>
              <span v-if="showCode && province.code" class="code-text">({{ province.code }})</span>
            </el-option>
          </el-select>
        </el-col>

        <!-- 城市选择 -->
        <el-col v-if="level >= 2" :span="levelSpan">
          <el-select
            v-model="selectedCity"
            :placeholder="cityPlaceholder"
            :disabled="disabled || !selectedProvince"
            :clearable="clearable"
            :size="size"
            :filterable="filterable"
            @change="handleCityChange"
          >
            <el-option
              v-for="city in cities"
              :key="city.value"
              :label="city.label"
              :value="city.value"
            >
              <span>{{ city.label }}</span>
              <span v-if="showCode && city.code" class="code-text">({{ city.code }})</span>
            </el-option>
          </el-select>
        </el-col>

        <!-- 区县选择 -->
        <el-col v-if="level >= 3" :span="levelSpan">
          <el-select
            v-model="selectedDistrict"
            :placeholder="districtPlaceholder"
            :disabled="disabled || !selectedCity"
            :clearable="clearable"
            :size="size"
            :filterable="filterable"
            @change="handleDistrictChange"
          >
            <el-option
              v-for="district in districts"
              :key="district.value"
              :label="district.label"
              :value="district.value"
            >
              <span>{{ district.label }}</span>
              <span v-if="showCode && district.code" class="code-text">({{ district.code }})</span>
            </el-option>
          </el-select>
        </el-col>
      </el-row>
    </div>

    <!-- 弹窗选择模式（兼容原有组件） -->
    <div v-else class="dialog-mode">
      <div class="el-select" @click.stop="openDialog" :style="styleWidth">
        <div class="el-select__tags" v-if="multiple" ref="tags" :style="{ 'max-width': inputWidth - 32 + 'px', width: '100%', cursor: 'pointer' }">
          <span v-if="collapseTags && tagsList.length">
            <el-tag :closable="!selectDisabled" :size="collapseTagSize" type="info" @close="deleteTag($event, 0)" disable-transitions>
              <span class="el-select__tags-text">{{ tagsList[0] }}</span>
            </el-tag>
            <el-tag v-if="tagsList.length > 1" :closable="false" type="info" disable-transitions>
              <span class="el-select__tags-text">+ {{ tagsList.length - 1 }}</span>
            </el-tag>
          </span>
          <transition-group @after-leave="resetInputHeight" v-if="!collapseTags">
            <el-tag v-for="(item, i) in tagsList" :key="item" :size="collapseTagSize" :closable="!selectDisabled" type="info" @close="deleteTag($event, i)" disable-transitions>
              <span class="el-select__tags-text">{{ item }}</span>
            </el-tag>
          </transition-group>
        </div>
        <el-input ref="reference" v-model="innerValue" type="text" :placeholder="currentPlaceholder" :disabled="selectDisabled" readonly :validate-event="false" :tabindex="multiple ? '-1' : null" @mouseenter.native="inputHovering = true" @mouseleave.native="inputHovering = false">
          <template slot="suffix">
            <i v-show="!showClose" :class="['el-select__caret', 'el-input__icon', 'el-icon-arrow-up']"></i>
            <i v-if="showClose" class="el-select__caret el-input__icon el-icon-circle-close" @click="handleClearClick"></i>
          </template>
        </el-input>
      </div>

      <el-dialog title="省市区选择" :close-on-click-modal="false" :visible.sync="visible" class="cu-dialog cu-dialog_center transfer-dialog" lock-scroll append-to-body width="800px" :modal-append-to-body="false" @close="onClose">
        <div class="transfer__body">
          <div class="transfer-pane">
            <div class="transfer-pane__tools">
              <span>全部数据</span>
            </div>
            <div class="transfer-pane__body">
              <el-tree :data="treeData" :props="treeProps" @node-click="handleNodeClick" check-strictly check-on-click-node :expand-on-click-node="false" class="cu-common-el-tree" node-key="id" v-loading="loading" lazy :load="loadNode">
                <span class="custom-tree-node" slot-scope="{ node, data }">
                  <i :class="data.icon"></i>
                  <span class="text">{{ node.label }}</span>
                  <span v-if="showCode && data.code" class="code-text">({{ data.code }})</span>
                </span>
              </el-tree>
            </div>
          </div>
          <div class="transfer-pane">
            <div class="transfer-pane__tools">
              <span>已选</span>
              <el-button @click="removeAll" type="text" class="removeAllBtn">清空列表</el-button>
            </div>
            <div class="transfer-pane__body shadow right-pane">
              <template>
                <div v-for="(item, index) in selectedData" :key="index" class="selected-item">
                  <span>{{ item }}</span>
                  <i class="el-icon-delete" @click="removeData(index)"></i>
                </div>
              </template>
            </div>
          </div>
        </div>
        <span slot="footer" class="dialog-footer">
          <el-button @click="visible = false">取消</el-button>
          <el-button type="primary" @click="confirm">确定</el-button>
        </span>
      </el-dialog>
    </div>
  </div>
</template>

<script>
import { getProvinceSelector, GetAreaByIds } from '@/api/system/province'
import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event'
import emitter from 'element-ui/src/mixins/emitter'

let {
  methods: { dispatch }
} = emitter

export default {
  name: 'AddressSelector',
  inject: {
    elForm: {
      default: ''
    },
    elFormItem: {
      default: ''
    }
  },
  props: {
    // 组件值
    value: {
      default: () => []
    },
    // 选择模式：cascader(级联选择器), select(下拉选择器), dialog(弹窗选择)
    mode: {
      type: String,
      default: 'cascader',
      validator: value => ['cascader', 'select', 'dialog'].includes(value)
    },
    // 行政级别：1(省), 2(市), 3(区县)
    level: {
      type: Number,
      default: 3,
      validator: value => [1, 2, 3].includes(value)
    },
    // 占位符
    placeholder: {
      type: String,
      default: '请选择地区'
    },
    // 省份占位符
    provincePlaceholder: {
      type: String,
      default: '请选择省份'
    },
    // 城市占位符
    cityPlaceholder: {
      type: String,
      default: '请选择城市'
    },
    // 区县占位符
    districtPlaceholder: {
      type: String,
      default: '请选择区县'
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false
    },
    // 是否支持多选
    multiple: {
      type: Boolean,
      default: false
    },
    // 多选时是否折叠标签
    collapseTags: {
      type: Boolean,
      default: false
    },
    // 是否可清空
    clearable: {
      type: Boolean,
      default: true
    },
    // 是否显示完整路径
    showAllLevels: {
      type: Boolean,
      default: true
    },
    // 分隔符
    separator: {
      type: String,
      default: ' / '
    },
    // 组件尺寸
    size: {
      type: String,
      default: '',
      validator: value => ['', 'medium', 'small', 'mini'].includes(value)
    },
    // 样式宽度
    styleWidth: {
      type: Object,
      default: () => ({ width: '100%' })
    },
    // 是否可搜索
    filterable: {
      type: Boolean,
      default: true
    },
    // 是否显示编码
    showCode: {
      type: Boolean,
      default: false
    },
    // 返回值类型：ids(返回ID数组), objects(返回对象数组)
    returnType: {
      type: String,
      default: 'ids',
      validator: value => ['ids', 'objects'].includes(value)
    }
  },
  data() {
    return {
      // 级联选择器相关
      cascaderOptions: [],
      selectedValues: [],
      cascaderProps: {
        value: 'id',
        label: 'fullName',
        children: 'children',
        lazy: true,
        lazyLoad: this.lazyLoadCascader,
        multiple: this.multiple,
        checkStrictly: this.multiple,
        changeOnSelect: !this.multiple
      },
      
      // 下拉选择器相关
      provinces: [],
      cities: [],
      districts: [],
      selectedProvince: '',
      selectedCity: '',
      selectedDistrict: '',
      
      // 弹窗选择器相关
      treeData: [],
      visible: false,
      loading: false,
      nodeId: '',
      innerValue: '',
      treeProps: {
        children: 'children',
        label: 'fullName',
        isLeaf: 'isLeaf'
      },
      selectedData: [],
      selectedIds: [],
      tagsList: [],
      inputHovering: false,
      inputWidth: 0,
      initialInputHeight: 0
    }
  },
  computed: {
    // 下拉选择器每列宽度
    levelSpan() {
      return Math.floor(24 / this.level)
    },
    // 是否显示清除按钮
    showClose() {
      let hasValue = Array.isArray(this.value) && this.value.length > 0
      let criteria = this.clearable && !this.selectDisabled && this.inputHovering && hasValue
      return criteria
    },
    // 当前占位符
    currentPlaceholder() {
      if (this.multiple && Array.isArray(this.value) && this.value.length) {
        return ''
      } else {
        return this.placeholder
      }
    },
    // 是否禁用选择
    selectDisabled() {
      return this.disabled || (this.elForm || {}).disabled
    },
    // 表单项尺寸
    _elFormItemSize() {
      return (this.elFormItem || {}).elFormItemSize
    },
    // 选择器尺寸
    selectSize() {
      return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size
    },
    // 折叠标签尺寸
    collapseTagSize() {
      return ['small', 'mini'].indexOf(this.selectSize) > -1 ? 'mini' : 'small'
    }
  },
  created() {
    this.initComponent()
  },
  mounted() {
    if (this.mode === 'dialog') {
      this.initDialogMode()
    }
    this.setDefaultValue()
  },
  beforeDestroy() {
    if (this.$el && this.handleResize) {
      removeResizeListener(this.$el, this.handleResize)
    }
  },
  watch: {
    value: {
      handler(val) {
        this.setDefaultValue()
      },
      deep: true
    },
    mode() {
      this.initComponent()
    },
    level() {
      this.initComponent()
    }
  },
  methods: {
    /**
     * 初始化组件
     */
    initComponent() {
      if (this.mode === 'cascader') {
        this.initCascaderMode()
      } else if (this.mode === 'select') {
        this.initSelectMode()
      } else if (this.mode === 'dialog') {
        this.nodeId = '-1'
        this.initDialogData()
      }
    },

    /**
     * 初始化级联选择器模式
     */
    async initCascaderMode() {
      try {
        const res = await getProvinceSelector('-1')
        this.cascaderOptions = res.data.list.map(item => ({
          ...item,
          leaf: item.isLeaf || this.level === 1
        }))
      } catch (error) {
        console.error('初始化级联选择器失败:', error)
      }
    },

    /**
     * 级联选择器懒加载
     */
    async lazyLoadCascader(node, resolve) {
      try {
        const { level, value } = node
        if (level >= this.level) {
          resolve([])
          return
        }
        
        const res = await getProvinceSelector(value)
        const children = res.data.list.map(item => ({
          ...item,
          leaf: item.isLeaf || level + 1 >= this.level
        }))
        resolve(children)
      } catch (error) {
        console.error('级联选择器懒加载失败:', error)
        resolve([])
      }
    },

    /**
     * 初始化下拉选择器模式
     */
    async initSelectMode() {
      try {
        const res = await getProvinceSelector('-1')
        this.provinces = res.data.list.map(item => ({
          value: item.id,
          label: item.fullName,
          code: item.code
        }))
      } catch (error) {
        console.error('初始化省份数据失败:', error)
      }
    },

    /**
     * 初始化弹窗模式
     */
    initDialogMode() {
      addResizeListener(this.$el, this.handleResize)
      
      const reference = this.$refs.reference
      if (reference && reference.$el) {
        const sizeMap = {
          medium: 36,
          small: 32,
          mini: 28
        }
        const input = reference.$el.querySelector('input')
        this.initialInputHeight = input.getBoundingClientRect().height || sizeMap[this.selectSize]
      }
      
      if (this.multiple) {
        this.resetInputHeight()
      }
      
      this.$nextTick(() => {
        if (reference && reference.$el) {
          this.inputWidth = reference.$el.getBoundingClientRect().width
        }
      })
    },

    /**
     * 初始化弹窗数据
     */
    async initDialogData() {
      try {
        this.loading = true
        const res = await getProvinceSelector(this.nodeId)
        this.treeData = res.data.list.map(value => ({
          ...value,
          isLeaf: value.isLeaf
        }))
        this.loading = false
      } catch (error) {
        console.error('初始化弹窗数据失败:', error)
        this.loading = false
      }
    },

    /**
     * 级联选择器变化事件
     */
    handleCascaderChange(value) {
      // 处理单选模式下的选择
      if (!this.multiple && Array.isArray(value) && value.length > 0) {
        // 确保选择的层级符合要求
        if (value.length >= this.level) {
          this.emitChange(value.slice(0, this.level))
        } else {
          this.emitChange(value)
        }
      } else {
        this.emitChange(value)
      }
    },

    /**
     * 级联选择器展开变化事件
     */
    handleExpandChange(value) {
      this.$emit('expand-change', value)
    },

    /**
     * 省份变化事件
     */
    async handleProvinceChange(value) {
      this.selectedCity = ''
      this.selectedDistrict = ''
      this.cities = []
      this.districts = []
      
      if (value && this.level >= 2) {
        try {
          const res = await getProvinceSelector(value)
          this.cities = res.data.list.map(item => ({
            value: item.id,
            label: item.fullName,
            code: item.code
          }))
        } catch (error) {
          console.error('加载城市数据失败:', error)
        }
      }
      
      this.emitSelectChange()
    },

    /**
     * 城市变化事件
     */
    async handleCityChange(value) {
      this.selectedDistrict = ''
      this.districts = []
      
      if (value && this.level >= 3) {
        try {
          const res = await getProvinceSelector(value)
          this.districts = res.data.list.map(item => ({
            value: item.id,
            label: item.fullName,
            code: item.code
          }))
        } catch (error) {
          console.error('加载区县数据失败:', error)
        }
      }
      
      this.emitSelectChange()
    },

    /**
     * 区县变化事件
     */
    handleDistrictChange() {
      this.emitSelectChange()
    },

    /**
     * 下拉选择器变化事件发射
     */
    emitSelectChange() {
      const values = []
      const objects = []
      
      if (this.selectedProvince) {
        const province = this.provinces.find(p => p.value === this.selectedProvince)
        values.push(this.selectedProvince)
        if (province) objects.push({ id: province.value, fullName: province.label, code: province.code })
      }
      
      if (this.selectedCity && this.level >= 2) {
        const city = this.cities.find(c => c.value === this.selectedCity)
        values.push(this.selectedCity)
        if (city) objects.push({ id: city.value, fullName: city.label, code: city.code })
      }
      
      if (this.selectedDistrict && this.level >= 3) {
        const district = this.districts.find(d => d.value === this.selectedDistrict)
        values.push(this.selectedDistrict)
        if (district) objects.push({ id: district.value, fullName: district.label, code: district.code })
      }
      
      this.emitChange(values, objects)
    },

    /**
     * 统一的变化事件发射
     */
    emitChange(values, objects = []) {
      const result = this.returnType === 'objects' ? objects : values
      this.$emit('input', result)
      this.$emit('change', result, objects)
      dispatch.call(this, 'ElFormItem', 'el.form.change', result)
    },

    /**
     * 设置默认值
     */
    async setDefaultValue() {
      if (!this.value || !this.value.length) {
        this.clearValues()
        return
      }
      
      if (this.mode === 'cascader') {
        this.selectedValues = Array.isArray(this.value[0]) ? this.value : [this.value]
      } else if (this.mode === 'select') {
        await this.setSelectDefaultValue()
      } else if (this.mode === 'dialog') {
        await this.setDialogDefaultValue()
      }
    },

    /**
     * 设置下拉选择器默认值
     */
    async setSelectDefaultValue() {
      try {
        const values = Array.isArray(this.value[0]) ? this.value[0] : this.value
        
        if (values.length > 0) {
          this.selectedProvince = values[0]
          await this.handleProvinceChange(values[0])
        }
        
        if (values.length > 1 && this.level >= 2) {
          this.selectedCity = values[1]
          await this.handleCityChange(values[1])
        }
        
        if (values.length > 2 && this.level >= 3) {
          this.selectedDistrict = values[2]
        }
      } catch (error) {
        console.error('设置下拉选择器默认值失败:', error)
      }
    },

    /**
     * 设置弹窗选择器默认值
     */
    async setDialogDefaultValue() {
      try {
        let selectedIds = this.multiple ? this.value : [this.value]
        const res = await GetAreaByIds(selectedIds)
        
        this.selectedIds = JSON.parse(JSON.stringify(selectedIds))
        this.selectedData = res.data.map(o => o.join('/'))
        
        if (this.multiple) {
          this.innerValue = ''
          this.tagsList = JSON.parse(JSON.stringify(this.selectedData))
        } else {
          this.innerValue = this.selectedData.join(',')
        }
        
        this.$nextTick(() => {
          if (this.multiple) {
            this.resetInputHeight()
          }
        })
      } catch (error) {
        console.error('设置弹窗选择器默认值失败:', error)
      }
    },

    /**
     * 清空所有值
     */
    clearValues() {
      this.selectedValues = []
      this.selectedProvince = ''
      this.selectedCity = ''
      this.selectedDistrict = ''
      this.cities = []
      this.districts = []
      this.innerValue = ''
      this.selectedData = []
      this.selectedIds = []
      this.tagsList = []
    },

    /**
     * 清空操作
     */
    clear() {
      if (this.selectDisabled) return
      this.clearValues()
      this.emitChange([])
    },

    /**
     * 焦点事件
     */
    handleFocus(event) {
      this.$emit('focus', event)
    },

    /**
     * 失焦事件
     */
    handleBlur(event) {
      this.$emit('blur', event)
    },

    // ========== 弹窗模式相关方法 ==========
    
    /**
     * 打开弹窗
     */
    openDialog() {
      if (this.selectDisabled) return
      this.visible = true
      this.nodeId = '-1'
      this.setDefaultValue()
    },

    /**
     * 关闭弹窗
     */
    onClose() {
      // 弹窗关闭事件
    },

    /**
     * 懒加载树节点
     */
    loadNode(node, resolve) {
      if (node.level === 0) {
        this.nodeId = '-1'
        return resolve(this.treeData)
      }
      
      this.nodeId = node.data.id
      getProvinceSelector(this.nodeId).then(res => {
        const list = res.data.list.map(value => ({
          ...value,
          isLeaf: node.level >= this.level ? true : value.isLeaf
        }))
        resolve(list)
      })
    },

    /**
     * 获取节点路径
     */
    getNodePath(node) {
      let fullPath = []
      const loop = node => {
        if (node.level) fullPath.unshift(node.data)
        if (node.parent) loop(node.parent)
      }
      loop(node)
      return fullPath
    },

    /**
     * 树节点点击事件
     */
    handleNodeClick(data, node) {
      if (!node.isLeaf) return
      
      const nodePath = this.getNodePath(node)
      let currId = nodePath.map(o => o.id)
      
      if (currId.length !== this.level + 1) return
      
      let currData = nodePath.map(o => o.fullName).join('/')
      
      if (this.multiple) {
        const boo = this.selectedIds.some(o => o.join('/') === currId.join('/'))
        if (boo) return
        this.selectedIds.push(currId)
        this.selectedData.push(currData)
      } else {
        this.selectedIds = [currId]
        this.selectedData = [currData]
      }
    },

    /**
     * 移除所有选中项
     */
    removeAll() {
      this.selectedData = []
      this.selectedIds = []
    },

    /**
     * 移除指定选中项
     */
    removeData(index) {
      this.selectedData.splice(index, 1)
      this.selectedIds.splice(index, 1)
    },

    /**
     * 确认选择
     */
    confirm() {
      let selectedData = []
      for (let i = 0; i < this.selectedIds.length; i++) {
        let item = []
        let selectedNames = this.selectedData[i].split('/')
        for (let j = 0; j < this.selectedIds[i].length; j++) {
          item.push({
            id: this.selectedIds[i][j],
            fullName: selectedNames[j]
          })
        }
        selectedData.push(item)
      }
      
      if (this.multiple) {
        this.innerValue = ''
        this.tagsList = JSON.parse(JSON.stringify(this.selectedData))
        this.emitChange(this.selectedIds, selectedData)
      } else {
        this.innerValue = this.selectedData.join(',')
        this.emitChange(this.selectedIds[0] || [], selectedData[0] || [])
      }
      
      this.visible = false
    },

    /**
     * 删除标签
     */
    deleteTag(event, index) {
      this.selectedData.splice(index, 1)
      this.selectedIds.splice(index, 1)
      this.confirm()
      event.stopPropagation()
    },

    /**
     * 清除按钮点击
     */
    handleClearClick(event) {
      this.selectedData = []
      this.selectedIds = []
      this.confirm()
      event.stopPropagation()
    },

    /**
     * 重置输入框宽度
     */
    resetInputWidth() {
      this.inputWidth = this.$refs.reference.$el.getBoundingClientRect().width
    },

    /**
     * 处理尺寸变化
     */
    handleResize() {
      this.resetInputWidth()
      if (this.multiple) this.resetInputHeight()
    },

    /**
     * 重置输入框高度
     */
    resetInputHeight() {
      if (this.collapseTags) return
      
      this.$nextTick(() => {
        if (!this.$refs.reference) return
        
        let inputChildNodes = this.$refs.reference.$el.childNodes
        let input = [].filter.call(inputChildNodes, item => item.tagName === 'INPUT')[0]
        const tags = this.$refs.tags
        const tagsHeight = tags ? Math.round(tags.getBoundingClientRect().height) : 0
        const sizeInMap = this.initialInputHeight || 40
        
        input.style.height = this.selectedData.length === 0
          ? sizeInMap + 'px'
          : Math.max(tags ? (tagsHeight + (tagsHeight > sizeInMap ? 6 : 0)) : 0, sizeInMap) + 'px'
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.address-selector {
  width: 100%;
  
  .code-text {
    color: #999;
    font-size: 12px;
    margin-left: 4px;
  }
  
  .select-mode {
    .el-col {
      margin-bottom: 0;
    }
  }
  
  .dialog-mode {
    .transfer__body {
      display: flex;
      height: 400px;
      
      .transfer-pane {
        flex: 1;
        border: 1px solid #ebeef5;
        border-radius: 4px;
        overflow: hidden;
        
        &:first-child {
          margin-right: 10px;
        }
        
        .transfer-pane__tools {
          height: 40px;
          line-height: 40px;
          background: #f5f7fa;
          margin: 0;
          padding: 0 15px;
          border-bottom: 1px solid #ebeef5;
          box-sizing: border-box;
          color: #000;
          display: flex;
          justify-content: space-between;
          align-items: center;
          
          .removeAllBtn {
            padding: 0;
            font-size: 12px;
          }
        }
        
        .transfer-pane__body {
          height: calc(100% - 40px);
          overflow: auto;
          
          &.right-pane {
            padding: 10px;
            
            .selected-item {
              display: flex;
              justify-content: space-between;
              align-items: center;
              padding: 8px 12px;
              margin-bottom: 5px;
              background: #f0f9ff;
              border: 1px solid #b3d8ff;
              border-radius: 4px;
              font-size: 12px;
              
              .el-icon-delete {
                cursor: pointer;
                color: #f56c6c;
                
                &:hover {
                  color: #f78989;
                }
              }
            }
          }
        }
      }
    }
    
    .custom-tree-node {
      display: flex;
      align-items: center;
      
      .text {
        margin-left: 5px;
      }
    }
  }
}

// 兼容原有样式
.popupSelect-container {
  .el-select {
    cursor: pointer;
    
    .el-select__tags {
      .el-tag {
        .el-select__tags-text {
          max-width: 100%;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }
      }
    }
  }
}

.cu-dialog {
  &.transfer-dialog {
    .el-dialog__body {
      padding: 20px;
    }
  }
}

.cu-common-el-tree {
  .el-tree-node__content {
    height: 32px;
    
    &:hover {
      background-color: #f5f7fa;
    }
  }
}
</style>